
#include "SaveMotionDialog.h"
#include "ui_SaveMotionDialog.h"

#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>
#include <MMM/Motion/MotionWriterXML.h>
#include <algorithm>

SaveMotionDialog::SaveMotionDialog(MMM::MotionList motions, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SaveMotionDialog),
    motions(motions),
    motionChanged(false)
{
    ui->setupUi(this);

    std::vector<std::string> motionNames;
    for (auto motion : motions) motionNames.push_back(motion->getName());
    motionList = new MotionListWidget(motionNames);

    ui->motionListLayout->addWidget(motionList);

    connect(ui->saveButton, SIGNAL(clicked()), this, SLOT(saveMotions()));
    connect(ui->cancelButton, SIGNAL(clicked()), this, SLOT(close()));
}

SaveMotionDialog::~SaveMotionDialog()
{
    delete ui;
}

void SaveMotionDialog::saveMotions() {
    MMM::MotionList motions;
    try {
        motions = getChoosenMotions();
    }
    catch (MMM::Exception::MMMException &e) {
        errorMessageBox(e.what());
        return;
    }

    QSettings settings;
    std::string motionFilePath = QFileDialog::getSaveFileName(this, tr("Save motions"), settings.value("motion/path", "").toString().replace(".c3d", ".xml"), tr("XML files (*.xml)")).toStdString();
    if (!motionFilePath.empty()) {
        this->close();
        settings.setValue("motion/searchpath", QString::fromStdString(motionFilePath));
        if (saveMotions(motions, motionFilePath)) {
            settings.setValue("motion/path", QString::fromStdString(motionFilePath));
            settings.setValue("motion/type", QString::fromStdString("MMM"));
            emit motionSaved();
            if (motionChanged && QMessageBox::Yes == QMessageBox::question(this, tr("Reload motion?"), tr("The saved file contains changes to your current opened motion. Do you want reload the saved motion file?"), QMessageBox::No|QMessageBox::Yes)) {
                emit openMotion(motionFilePath);
            }
        }
    }
}

MMM::MotionList SaveMotionDialog::getChoosenMotions() {
    std::vector<MMM::MotionListConfigurationPtr> configurations = motionList->getConfigurations(); // forward MMMException
    std::sort(configurations.begin(), configurations.end(), MMM::SortByNewIndexFunctor());
    MMM::MotionList motions;
    int index = 0;
    for (auto configuration : configurations) {
        if (!configuration->isIgnoreMotion()) {
            MMM::MotionPtr motion = this->motions.at(configuration->getIndex())->clone();
            if (index != configuration->getIndex() || motion->getName() != configuration->getMotionName()) motionChanged = true;
            motion->setName(configuration->getMotionName());
            motions.push_back(motion);
        }
        else motionChanged = true;
        index++;
    }
    if (motions.size() == 0) throw MMM::Exception::MMMException("Choose motions to save!");
    return motions;
}

bool SaveMotionDialog::saveMotions(MMM::MotionList motions, const std::string &motionFilePath) {
    MMM::MotionWriterXMLPtr motionWriter(new MMM::MotionWriterXML());
    try {
        motionWriter->writeMotion(motions, motionFilePath);
        return true;
    } catch(MMM::Exception::MMMException &e) {
        errorMessageBox(e.what());
        return false;
    }
}

void SaveMotionDialog::errorMessageBox(const std::string &message) {
    QMessageBox* msgBox = new QMessageBox(this);
    msgBox->setText(QString::fromStdString(message));
    MMM_ERROR << message << std::endl;
    msgBox->exec();
}
